package homework3;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;

/**
 * CalculateReturn()
 * 
 * @data 2013.7.10
 * @declaration Using LinkedList to read data, and calculate the data's linear
 *              regression and it's parameters
 * 
 * @author 121250185
 *         Listing Contents:
 * @method: main(String[] args) 
 * 			,answerYk(double betaOne, double betaZero)
 * 			,relation(LinkedList<Double> dataX, LinkedList<Double> dataY)
 *  		,betaZeroCal(LinkedList<Double> dataX, LinkedList<Double> dataY, double betaOne)
 *          ,betaOneCal(LinkedList<Double> dataX, LinkedList<Double> dataY)
 *          ,mulAndAdd(LinkedList<Double> dataX, LinkedList<Double> dataY)
 * 			,calculateMean(LinkedList<Double> data, double mean)
 *          ,readFile(String path)
 */

public class CalculateReturn {
	public static final int X_K = 386;
		
	static BufferedReader br = null;
	static int line = 0;

	public static void main(String[] args) {
		LinkedList<Double> dataX = readFile("hw3data1.txt");
		LinkedList<Double> dataY = readFile("hw3data3.txt");
		double betaOne = betaOneCal(dataX, dataY);
		double betaZero = betaZeroCal(dataX, dataY, betaOne);
		System.out.println(String.format(String.format("The betaZero is %.4f ", betaZero) + "and the betaOne is %.4f ", betaOne));
		double r = relation(dataX,dataY);
		System.out.println(String.format("The r is %.4f ", r) + String.format("and the r^2 is %.4f ", r * r));
		System.out.println(String.format("The yk is %.4f ", answerYk(betaOne, betaZero)));
	}// end

	/**
	 * answerYk(double betaOne, double betaZero)
	 * 
	 * @declaration: Calculate the yk
	 * @param betaOne, betaZero
	 * @return yk
	 */
	private static double answerYk(double betaOne, double betaZero) {
		return betaZero + betaOne * X_K;
	}// end

	/**
	 * relation(LinkedList<Double> dataX, LinkedList<Double> dataY)
	 * 
	 * @declaration: Calculate the r
	 * @param dataX, dataY
	 * @return r
	 */
	private static double relation(LinkedList<Double> dataX, LinkedList<Double> dataY) {
		LinkedList<Double> dataTemp = new LinkedList<Double>();
		for (Double double1 : dataX) {
			dataTemp.add(1.0);
		}
		double temp0 = dataX.size() * mulAndAdd(dataX, dataY);
		double temp1 = mulAndAdd(dataX, dataTemp) * mulAndAdd(dataY, dataTemp);
		double temp2 = dataX.size() * mulAndAdd(dataX, dataX) - mulAndAdd(dataX, dataTemp) * mulAndAdd(dataX, dataTemp);
		double temp3 = dataX.size() * mulAndAdd(dataY, dataY) - mulAndAdd(dataY, dataTemp) * mulAndAdd(dataY, dataTemp);
		double r = (temp0 - temp1) / Math.sqrt(temp3*temp2);
		return r;
	}// end
	
	/**
	 * betaZeroCal(LinkedList<Double> dataX, LinkedList<Double> dataY, double betaOne)
	 * 
	 * @declaration: Calculate the betaZero
	 * @param dataX, dataY, betaOnes
	 * @return betaZero
	 */
	private static double betaZeroCal(LinkedList<Double> dataX, LinkedList<Double> dataY, double betaOne) {
		double meanX = calculateMean(dataX, 0);
		double meanY = calculateMean(dataY, 0);
		double betaZero = meanY - betaOne * meanX;
		return betaZero;
	}// end
	
	/**
	 * betaOneCal(LinkedList<Double> dataX, LinkedList<Double> dataY)
	 * 
	 * @declaration: Calculate the betaOne
	 * @param dataX, dataY
	 * @return betaOne
	 */
	private static double betaOneCal(LinkedList<Double> dataX, LinkedList<Double> dataY) {
		double meanX = calculateMean(dataX, 0);
		double meanY = calculateMean(dataY, 0);
		double temp0 = mulAndAdd(dataX, dataY);
		double temp1 = mulAndAdd(dataX, dataX);
		double betaOne = (temp0 - dataX.size() * meanX * meanY)/(temp1 - dataX.size() * meanX * meanX);
		return betaOne;
	}// end

	/**
	 * mulAndAdd(LinkedList<Double> dataX, LinkedList<Double> dataY)
	 * 
	 * @param dataY 
	 * @param dataX 
	 * @declaration: Calculate 2 data multiply and add them
	 * @return mean
	 */
	private static double mulAndAdd(LinkedList<Double> dataX, LinkedList<Double> dataY) {
		double temp = 0.0;
		for (int i = 0; i < dataX.size(); i++) {
			temp += dataX.get(i) * dataY.get(i);
		}
		return temp;
	}// end

	/**
	 * calculateMean()
	 * 
	 * @declaration: Calculate the mean
	 * @return mean
	 */
	private static double calculateMean(LinkedList<Double> data, double mean) {
		for (double i : data) {
			mean += i;
		}
		return mean / data.size();
	}// end

	/**
	 * readFile(String path)
	 * 
	 * @declaration: read the data from file
	 * @param path
	 * @return
	 */
	public static LinkedList<Double> readFile(String path) {
		LinkedList<Double> data = new LinkedList<Double>();
		String temp = "";
		try {
			br = new BufferedReader(new FileReader(path));
			while ((temp = br.readLine()) != null) {
				data.add(Double.parseDouble(temp));
				line++;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return data;
	}// end
}
